package com.jason.library;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.swing.Spring;

/**
 * @author ChenBaoyang
 * @description: ProxyMain
 * @date 7/7/21 10:23
 */
public class ProxyMain {

    public static void main(String[] args) {

//        AdminService service = new AdminServiceImpl();
//        AdminServiceStaticProxy proxy = new AdminServiceStaticProxy(service);
//        proxy.find();
//        proxy.insert("jason");
//        Info info = (Info) proxy.find();
//        System.out.println(info.name + "," + info.id);

        // 方法一
        System.out.println("============ 方法一 ==============");
        AdminService adminService = new AdminServiceImpl();
        System.out.println("代理的目标对象：" + adminService.getClass());

        InvocationHandler handler = new AdminServiceInvocation(adminService);
        AdminServiceDynamicProxy dynamicProxy = new AdminServiceDynamicProxy(adminService, handler);
        System.out.println("代理对象：" + dynamicProxy.getClass());

        AdminService proxy1 = (AdminService) dynamicProxy.getPersonProxy();
        System.out.println("find 返回对象：" + proxy1.getClass());
        Info info1 = (Info) proxy1.find();
        System.out.println(info1.name + "," + info1.id);
        proxy1.insert("jason");
        proxy1.update();

        System.out.println("----------------------------------");

        //方法二
        System.out.println("============ 方法二 ==============");
        AdminService target = new AdminServiceImpl();
        AdminServiceInvocation invocation = new AdminServiceInvocation(adminService);
        AdminService proxy2 = (AdminService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocation);

        Object obj2 = proxy2.find();
        System.out.println("find 返回对象：" + obj2.getClass());
        System.out.println("----------------------------------");
        proxy2.update();

        //方法三
        System.out.println("============ 方法三 ==============");
        final AdminService target3 = new AdminServiceImpl();
        AdminService proxy3 = (AdminService) Proxy.newProxyInstance(target3.getClass().getClassLoader(), target3.getClass().getInterfaces(), new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("判断用户是否有权限进行操作");
                Object obj = method.invoke(target3, args);
                System.out.println("记录用户执行操作的用户信息、更改内容和时间等");
                return obj;
            }
        });

        Object obj3 = proxy3.find();
        System.out.println("find 返回对象：" + obj3.getClass());
        System.out.println("----------------------------------");
        proxy3.update();
    }


    /*************************************** 静态代理 - start ****************************************/

    public static class Info {
        public String name;
        public int id;

        public Info(String name, int id) {
            this.name = name;
            this.id = id;
        }

        @Override
        public String toString() {
            return "Info{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    '}';
        }
    }

    /**
     * 接口
     */
    public interface AdminService {
        void update();

        Object find();

        void insert(String name);
    }

    /**
     * 实现者
     */
    public static class AdminServiceImpl implements AdminService {

        @Override
        public void update() {
            System.out.println("AdminServiceImpl - update");
        }

        @Override
        public Object find() {
            System.out.println("AdminServiceImpl - find");
            return new Info("AdminServiceImpl", 111);
        }

        @Override
        public void insert(String name) {
            System.out.println("AdminServiceImpl - insert: name-" + name);
        }
    }

    /**
     * 代理者
     */
    public static class AdminServiceStaticProxy implements AdminService {

        private AdminService service;

        public AdminServiceStaticProxy(AdminService service) {
            this.service = service;
        }

        @Override
        public void update() {
            System.out.println("AdminServiceStaticProxy - update");
            service.update();
        }

        @Override
        public Object find() {
            System.out.println("AdminServiceStaticProxy - find");
            return service.find();

        }

        @Override
        public void insert(String name) {
            System.out.println("AdminServiceStaticProxy - insert");
            service.insert(name);
        }
    }

    /*************************************** 静态代理 - end ****************************************/

    /*************************************** 动态代理 - start ****************************************/

    public static class AdminServiceInvocation implements InvocationHandler {

        private Object target;

        public AdminServiceInvocation(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            System.out.println("AdminServiceInvocation - before");
            Object obj = method.invoke(target, objects);
            System.out.println("AdminServiceInvocation - after");
            return obj;
        }
    }

    public static class AdminServiceDynamicProxy {
        private Object target;
        private InvocationHandler invocationHandler;
        public AdminServiceDynamicProxy(Object target,InvocationHandler invocationHandler){
            this.target = target;
            this.invocationHandler = invocationHandler;
        }

        public Object getPersonProxy() {
            Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);
            return obj;
        }
    }

    /*************************************** 动态代理 - end ****************************************/
}
